package com.linkhub.oms.admin.modules.user.account.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.linkhub.oms.admin.common.exception.ExceptionFactory;
import com.linkhub.oms.admin.modules.user.account.domain.dto.UserAccountDTO;
import com.linkhub.oms.admin.modules.user.account.domain.vo.UserAccountVO;
import com.linkhub.oms.admin.modules.user.account.service.IUserAccountService;
import com.linkhub.oms.common.enums.mp.DataStatusEnum;
import com.linkhub.oms.common.enums.mp.TransactionTypeEnum;
import com.linkhub.oms.common.util.QtBigDecimalUtil;
import com.linkhub.oms.common.util.QtOptionalUtil;
import com.linkhub.oms.dao.mapper.UserAccountEntityMapper;
import com.linkhub.oms.entity.UserAccountEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Objects;

/**
 * <p>
 * 用户账户表 服务实现类
 * </p>
 *
 * @author Frank
 * @since 2024-05-26
 */
@Service
@Slf4j
public class UserAccountServiceImpl extends ServiceImpl<UserAccountEntityMapper, UserAccountEntity> implements IUserAccountService {

    @Override
    public UserAccountVO getUserAccount(String userId) {
        UserAccountEntity accountEntity = lambdaQuery()
                .eq(UserAccountEntity::getUserId, userId)
                .one();
        if (Objects.isNull(accountEntity)) {
            try {
                accountEntity = new UserAccountEntity();
                accountEntity.setUserId(userId);
                this.save(accountEntity);
            } catch (Exception e) {
                log.info("user account already exists.userId:{}", userId);
            }
            return new UserAccountVO();
        }
        if (!Objects.equals(DataStatusEnum.ENABLE, accountEntity.getDataStatus())) {
            throw ExceptionFactory.getI18nBizException("user.account.invalid");
        }
        return new UserAccountVO(accountEntity);
    }

    @Override
    public void reduceTotalBalance(String userId, BigDecimal expense) {
        UserAccountEntity accountEntity = lambdaQuery()
                .eq(UserAccountEntity::getUserId, userId)
                .eq(UserAccountEntity::getDataStatus, DataStatusEnum.ENABLE)
                .one();
        BigDecimal total = QtOptionalUtil.of(accountEntity)
                .map(UserAccountEntity::getTotalBalance)
                .orElse(BigDecimal.ZERO);
        BigDecimal balance = NumberUtil.sub(total, expense);

        UserAccountEntity update = new UserAccountEntity();
        update.setTotalBalance(balance);

        super.lambdaUpdate()
                .eq(UserAccountEntity::getUserId, userId)
                .update(update);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserAccountDTO updateAccountAmount(String userId, BigDecimal operateAmount, TransactionTypeEnum transactionTypeEnum) {
        UserAccountEntity userAccountEntity = baseMapper.selectForUpdate(userId);
        if (Objects.isNull(userAccountEntity)) {
            throw ExceptionFactory.getI18nBizException("user.account.does.not.exist");
        }
        BigDecimal totalBalanceUpd = userAccountEntity.getTotalBalance();
        BigDecimal frozenBalanceUpd = userAccountEntity.getFrozenBalance();
        if (TransactionTypeEnum.PAY.equals(transactionTypeEnum)) {
            totalBalanceUpd = totalBalanceUpd.subtract(operateAmount);
        }
        if (TransactionTypeEnum.INCOME.equals(transactionTypeEnum)) {
            totalBalanceUpd = totalBalanceUpd.add(operateAmount);
        }
        if (TransactionTypeEnum.FREEZE.equals(transactionTypeEnum)) {
            frozenBalanceUpd = frozenBalanceUpd.add(operateAmount);
        }
        if (TransactionTypeEnum.UN_FREEZE.equals(transactionTypeEnum)) {
            frozenBalanceUpd = frozenBalanceUpd.subtract(operateAmount);
        }
        if (QtBigDecimalUtil.lt(totalBalanceUpd, new BigDecimal(0))) {
            throw ExceptionFactory.getI18nBizException("user.account.balance.is.insufficient");
        }
        if (QtBigDecimalUtil.lt(frozenBalanceUpd, new BigDecimal(0))) {
            throw ExceptionFactory.getI18nBizException("user.account.unfrozen.balance.is.insufficient");
        }
        userAccountEntity.setTotalBalance(totalBalanceUpd);
        userAccountEntity.setFrozenBalance(frozenBalanceUpd);
        this.updateById(userAccountEntity);
        return new UserAccountDTO(totalBalanceUpd, frozenBalanceUpd);
    }


}
